﻿using System.Threading.Tasks;
using System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
using System.Linq;
using Domain;
using System.Net.Sockets;
using System.Net;
using Application.App.Command;
using Domain.Enums;
using Application.Common.Extensions;
using Application.Common.Interface;
using System.Text;
using Newtonsoft.Json;
using TouchSocket.Sockets;
using TouchSocket.Core;
using Application.Adapter;
using MediatR;
using Domain.Models.Cmd;
using Infrastructure.Services;
using System.Reflection;
using Domain.Models;
using TouchSocket.Http;
using System.Net.Http;
using System.Runtime.InteropServices;
using Microsoft.Extensions.Options;
using Domain.Options;
using Application.App.Queries;

namespace WebApi.Controllers
{
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class AppController : ApiControllerBase
    {
        private readonly ILogger<AppController> _logger;
        private readonly ITcpService _tcpService;
        private readonly ICustomTcpClient _customTcpClient;
        private readonly IHttpClientFactory _httpClientFactory;
        private readonly ApiConfigOptions _apiConfigOptions;

        public AppController(ITcpService tcpService, ILogger<AppController> logger, ICustomTcpClient customTcpClient, IHttpClientFactory httpClientFactory, IOptions<ApiConfigOptions> options)
        {
            _tcpService = tcpService;
            _logger = logger;
            _customTcpClient = customTcpClient;
            _httpClientFactory = httpClientFactory;
            this._apiConfigOptions = options.Value;
        }
        [HttpPost]
        public object GetAllIds()
        {
            var ids = _tcpService.GetIds();

            //var res = from de in Consts.devices
            //select new
            //{
            //    deviceId = de.Key,
            //    IPPort = de.Value?.ScoketIPPort ?? "",
            //    State = de.Value?.State == 1 ? "在线" : "离线",
            //};

            //return new { res, ids };

            return JsonConvert.SerializeObject(new { list= Consts.devices });
        }
        [HttpPost]
        public async Task<Result> SendCommand(SendCommand cmd)
        {
            return await Mediator.Send(cmd);
        }
        [HttpPost]
        public async Task ClientConnectServer()
        {
            try
            {
                ////模拟一个37的设备客户端
                //string ipAddress = "192.168.0.38";
                //int port = 6637;

                //// 创建一个终结点
                //IPAddress ipAddr = IPAddress.Parse(ipAddress);
                //IPEndPoint endPoint = new IPEndPoint(ipAddr, port);

                //// 创建 Socket
                //Socket clientSocket = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

                //// 连接到服务器
                //clientSocket.Connect(new IPEndPoint(IPAddress.Parse("192.168.0.38"), 6638));

                //// 要发送的消息

                //// 发送数据

                ////设备自动发送心跳
                //_ = Task.Factory.StartNew(async () =>
                //{
                //    while (true)
                //    {
                //        var startBytes = "A5091600000017".HexStringToByteArray().ToList();
                //        var vaildCode = startBytes.GetVaildByteCode();
                //        startBytes.Add(vaildCode);
                //        startBytes.Add(Consts.EndByte);
                //        var res = clientSocket.Send(startBytes.ToArray());
                //        await Console.Out.WriteLineAsync($"客户端16000000 -> 服务器  数据：{Convert.ToHexString(startBytes.ToArray())}");
                //        await Task.Delay(10000);

                //    }
                //});


                while (true)
                {
                    var startBytes = "A5091600000017".HexStringToByteArray().ToList();
                    var vaildCode = startBytes.GetVaildByteCode();
                    startBytes.Add(vaildCode);
                    startBytes.Add(Consts.EndByte);
                    _customTcpClient.Send(startBytes.ToArray());
                    await Console.Out.WriteLineAsync("customTcpClient  模拟一个socket  发送心跳");
                    await Task.Delay(600000);

                }


                // 关闭连接
                //clientSocket.Shutdown(SocketShutdown.Both);
                //clientSocket.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine("发生异常：" + ex.ToString());
            }
            return;
        }

        /// <summary>
        /// 复用socketclient  等待客户端返回
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost]

        public async Task<Result> SocketClientSendThenRecive(string DeviceId, DataType CmdType)
        {
            try
            {
                //设备开锁  res A5 0A 00F42401 1D05EA5AA50F00F4240114000000000064455AA50C00F4240112030000DF 5A
                Consts.CommandPackageLength.TryGetValue(CmdType, out var packageLength);
                var buffer = new List<byte>() { Consts.StartByte, packageLength };
                buffer.AddRange(DeviceId.HexStringToByteArray());
                buffer.Add(((int)CmdType).ToByte());
                var vaildCode = buffer.GetVaildByteCode();
                buffer.Add(vaildCode);
                buffer.Add(Consts.EndByte);

                //
                //var buffer = "A5091600000017".HexStringToByteArray().ToList();
                //buffer = buffer.GetVaildByteCode();
                //buffer.Add(vaildCode);
                //buffer.Add(Consts.EndByte);


                //注意   AdapterFilter.NoneAll   使用 result.Data     经过适配器才可以使用IRequestInfo
                Consts.DeviceToSocketId.TryGetValue(DeviceId, out var socketId);
                if (this._tcpService.SocketClients.TryGetSocketClient(socketId, out var client))
                {
                    var result = client.GetWaitingClient(new WaitingOptions() { AdapterFilter = AdapterFilter.NoneAll, BreakTrigger = true, ThrowBreakException = true }).SendThenResponse(buffer.ToArray(), timeout: 100000);
                    await Console.Out.WriteLineAsync($"复用socket 获取服务器返回：{Convert.ToHexString(result.Data)}");
                    return new Result(ResultCode.Success, Convert.ToHexString(result.Data));
                }
                else
                {
                    return new Result(ResultCode.Error, "没有这个ID");
                }
            }
            catch (Exception ex)
            {
                return new Result(ResultCode.Error, ex.Message);
            }
        }

        /// <summary>
        /// 复用socketclient直接发送指定命令
        /// </summary>
        /// <param name="DeviceId"></param>
        /// <param name="buffer"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<Result> SocketClientSendHexThenRecive(string DeviceId, string buffer)
        {
            //远程升级固件  A50900F424010DD45A       res A5 0A 00F42401 1D 05 EA 5A
            //校准命令 
            //通道校准命令
            Consts.DeviceToSocketId.TryGetValue(DeviceId, out var socketId);
            if (this._tcpService.SocketClients.TryGetSocketClient(socketId, out var client))
            {
                var result = client.GetWaitingClient(new WaitingOptions() { AdapterFilter = AdapterFilter.NoneAll, BreakTrigger = true, ThrowBreakException = true }).SendThenResponse(buffer.ByHexStringToBytes(), timeout: 100000);
                await Console.Out.WriteLineAsync($"复用socket 获取服务器返回：{Convert.ToHexString(result.Data)}");
                return new Result(ResultCode.Success, Convert.ToHexString(result.Data));
            }
            else
            {
                return new Result(ResultCode.Error, "没有这个ID");
            }

        }


        /// <summary>
        /// 手动创建tcpSocket 可接收两个tcp连接
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<Result> TestICustomClient(string str)
        {
            //必须手动连接
            //_customTcpClient.Connect();
            {
                //var startBytes = "A5091600000000".HexStringToByteArray().ToList();
                //var vaildCode = startBytes.GetVaildByteCode();
                //startBytes.Add(vaildCode);
                //startBytes.Add(Consts.EndByte);
                //await Console.Out.WriteLineAsync($"测试 customclient 两个tcp req  data:{Convert.ToHexString(startBytes.ToArray())}");
                //var res = _customTcpClient.SendThenReceive(startBytes.ToArray());
                //await Console.Out.WriteLineAsync($"测试 customclient 两个tcp res  data:{Convert.ToHexString(((BetweenAndRequestInfo)res.RequestInfo).Body)}");
                //return Result.FromSuccess(Convert.ToHexString(((BetweenAndRequestInfo)res.RequestInfo).Body));
            }
            {
                //上行一个
                //A50B16000001110101DA5A
                //出酒完成上报
                //A50C16000001120101643F5A
                //A50C00F42401120101F4D25A
                var startBytes = str.HexStringToByteArray().ToList();
                await Console.Out.WriteLineAsync($"测试 customclient 两个tcp req  data:{Convert.ToHexString(startBytes.ToArray())}");
                var res = _customTcpClient.SendThenReceive(startBytes.ToArray());
                await Console.Out.WriteLineAsync($"测试 customclient 两个tcp res  data:{Convert.ToHexString(((BetweenAndRequestInfo)res.RequestInfo).Body)}");
                return Result.FromSuccess(Convert.ToHexString(((BetweenAndRequestInfo)res.RequestInfo).Body));
            }
        }
        /// <summary>
        /// 测试注入的httpclientfactory
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<Result> TestHttpClient()
        {
            using var client = _httpClientFactory.CreateClient();
            client.BaseAddress = new Uri(_apiConfigOptions.BaseCallBackUrl);
            var res = await client.PostAsync(_apiConfigOptions.StateUpdateUrl, new StringContent(JsonConvert.SerializeObject(new { device ="123456",state = 1}),Encoding.UTF8, "application/json"));
            return Result.Success;
        }


        #region 具体命令类

        /// <summary>
        /// 设置开关机
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<Result> TimerStopStart(SetTimerStopAndStartDown model)
        {
            {

            }
            DateTime.TryParse(model.StopTime, out var stopTime);
            DateTime.TryParse(model.StartTime, out var startTime);


            Consts.CommandPackageLength.TryGetValue(model.CmdType, out var packageLength);
            var buffer = new List<byte>() { Consts.StartByte, packageLength };
            buffer.AddRange(model.DeviceId.HexStringToByteArray());
            buffer.Add(((int)model.CmdType).ToByte());


            buffer.Add(Convert.ToByte(stopTime.Hour.ToString("X"), 16));
            buffer.Add(Convert.ToByte(stopTime.Minute.ToString("X"), 16));
            buffer.Add(Convert.ToByte(startTime.Hour.ToString("X"), 16));
            buffer.Add(Convert.ToByte(startTime.Minute.ToString("X"), 16));


            var vaildCode = buffer.GetVaildByteCode();
            buffer.Add(vaildCode);
            buffer.Add(Consts.EndByte);
            await Console.Out.WriteLineAsync(Convert.ToHexString(buffer.ToArray()));
            //var result = _customTcpClient.SendThenReceive(buffer.ToArray(), AdapterFilter.WaitAdapter);
            //var data = result.RequestInfo.ToJson();
            //return Result.FromSuccess(data);
            return Result.Success;
        }

        [HttpPost]
        public async Task<Result> AdUpdate(AdUpdateDown model)
        {
            if (model.DownloadAddress.Length > 100 || model.DownloadAddress?.Split("/").LastOrDefault().Length > 32)
            {
                return Result.FromError("下载地址不符合规范");
            }
            var buffer = new List<byte>() { Consts.StartByte };
            buffer.AddRange(model.DeviceId.HexStringToByteArray());
            buffer.Add(((int)model.CmdType).ToByte());

            var adHex = model.AdNumber.ToString("X");
            if (adHex.Length < 4)
            {
                for (int i = adHex.Length; i < 4; i++)
                {
                    adHex = "0" + adHex;
                }
            }

            byte[] downByte = ("(" + model.DownloadAddress + ")").ToUTF8Bytes();

            buffer.AddRange(adHex.ByHexStringToBytes());
            buffer.AddRange(downByte);

            buffer.Insert(1, (downByte.Length + 11).ToByte());


            var vaildCode = buffer.GetVaildByteCode();
            buffer.Add(vaildCode);
            buffer.Add(Consts.EndByte);

            await Console.Out.WriteLineAsync(Convert.ToHexString(buffer.ToArray()));
            var result = _customTcpClient.SendThenReceive(buffer.ToArray(), AdapterFilter.WaitAdapter);
            var data = result.RequestInfo.ToJsonString();
            return Result.FromSuccess(data);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>

        [HttpPost]
        public async Task<Result> RemoteUpdate(RemoteUpdateFirmwareReq model)
        {
            #region 通用下行命令

            Consts.CommandPackageLength.TryGetValue(model.CmdType, out var packageLength);
            var buffer = new List<byte>() { Consts.StartByte, packageLength };
            buffer.AddRange(model.DeviceId.HexStringToByteArray());
            buffer.Add(((int)model.CmdType).ToByte());
            var vaildCode = buffer.GetVaildByteCode();
            buffer.Add(vaildCode);
            buffer.Add(Consts.EndByte);


            #endregion


            Console.WriteLine($"App Send Command Req:{Convert.ToHexString(buffer.ToArray())}");
            var result = _customTcpClient.SendThenReceive(buffer.ToArray(), AdapterFilter.WaitAdapter);

            var a = ((RemoteUpdateFirmwareReply)(((BetweenAndRequestInfo)result.RequestInfo).Data));

            await Console.Out.WriteLineAsync($"App Send Command Res Body:{Convert.ToHexString(((BetweenAndRequestInfo)result.RequestInfo).Body)}");
            return new Result(ResultCode.Success, ((BetweenAndRequestInfo)result.RequestInfo).Data.ToJsonString());

        }
        [HttpPost]
        public async Task<Result> OutOfWine(OutOfWineCommand cmd)
        {
            return await Mediator.Send(cmd);
        }

        [HttpPost]
        public async Task<Result> PlatFormReplyOOWEnd(PlatFormReplyOOWEndDown model)
        {
            Consts.CommandPackageLength.TryGetValue(model.CmdType, out var packageLength);
            var buffer = new List<byte>() { Consts.StartByte, packageLength };
            buffer.AddRange(model.DeviceId.HexStringToByteArray());
            buffer.Add(((int)model.CmdType).ToByte());

            buffer.Add(model.ChannelNumber.ToByte());
            buffer.Add(model.RunState.ToByte());

            var vaildCode = buffer.GetVaildByteCode();
            buffer.Add(vaildCode);
            buffer.Add(Consts.EndByte);


            Console.WriteLine($"App Send Command Req:{Convert.ToHexString(buffer.ToArray())}");
            var result = _customTcpClient.SendThenReceive(buffer.ToArray(), AdapterFilter.WaitAdapter);


            await Console.Out.WriteLineAsync($"App Send Command Res Body:{Convert.ToHexString(((BetweenAndRequestInfo)result.RequestInfo).Body)}");

            //回返回什么？？？
            return new Result(ResultCode.Success);
        }

        [HttpPost]
        public async Task<Result> SelectDeviceState(RunReq model)
        {
            Consts.CommandPackageLength.TryGetValue(DataType.查询设备命令下, out var packageLength);
            var buffer = new List<byte>() { Consts.StartByte, packageLength };
            buffer.AddRange(model.DeviceId.HexStringToByteArray());
            buffer.Add(((int)DataType.查询设备命令下).ToByte());
            var vaildCode = buffer.GetVaildByteCode();
            buffer.Add(vaildCode);
            buffer.Add(Consts.EndByte);



            Console.WriteLine($"App Send Command Req:{Convert.ToHexString(buffer.ToArray())}");
            var result = _customTcpClient.SendThenReceive(buffer.ToArray(), AdapterFilter.WaitAdapter);
            await Console.Out.WriteLineAsync($"App Send Command Res Body:{Convert.ToHexString(((BetweenAndRequestInfo)result.RequestInfo).Body)}");
            return new Result(ResultCode.Success, ((BetweenAndRequestInfo)result.RequestInfo).Data.ToJsonString());
        }


        [HttpPost]
        public async Task<Result> DeviceUnlock(RunReq model)
        {
            Consts.CommandPackageLength.TryGetValue(DataType.设备开锁命令下, out var packageLength);
            var buffer = new List<byte>() { Consts.StartByte, packageLength };
            buffer.AddRange(model.DeviceId.HexStringToByteArray());
            buffer.Add(((int)DataType.设备开锁命令下).ToByte());
            var vaildCode = buffer.GetVaildByteCode();
            buffer.Add(vaildCode);
            buffer.Add(Consts.EndByte);



            Console.WriteLine($"App Send Command Req:{Convert.ToHexString(buffer.ToArray())}");
            //var result = _customTcpClient.SendThenReceive(buffer.ToArray(), AdapterFilter.WaitAdapter);
            //await Console.Out.WriteLineAsync($"App Send Command Res Body:{Convert.ToHexString(((BetweenAndRequestInfo)result.RequestInfo).Body)}");
            //return new Result(ResultCode.Success, ((BetweenAndRequestInfo)result.RequestInfo).Data.ToJson());
            return Result.Success;
        }

        [HttpPost]
        public async Task<Result> ModifyServiceIp(RunReq model)
        {
            Consts.CommandPackageLength.TryGetValue(DataType.设备开锁命令下, out var packageLength);
            var buffer = new List<byte>() { Consts.StartByte, packageLength };
            buffer.AddRange(model.DeviceId.HexStringToByteArray());
            buffer.Add(((int)DataType.设备开锁命令下).ToByte());
            var vaildCode = buffer.GetVaildByteCode();
            buffer.Add(vaildCode);
            buffer.Add(Consts.EndByte);



            Console.WriteLine($"App Send Command Req:{Convert.ToHexString(buffer.ToArray())}");
            var result = _customTcpClient.SendThenReceive(buffer.ToArray(), AdapterFilter.WaitAdapter);
            await Console.Out.WriteLineAsync($"App Send Command Res Body:{Convert.ToHexString(((BetweenAndRequestInfo)result.RequestInfo).Body)}");
            return new Result(ResultCode.Success, ((BetweenAndRequestInfo)result.RequestInfo).Data.ToJsonString());
        }


        [HttpPost]
        public async Task<Result> CalibrateActuallyOOW(CalibrateActuallyOOWDown model)
        {
            if (model.WineNumber > 255)
            {
                return Result.FromError("校准实际出酒量必须小于255ml");
            }

            Consts.CommandPackageLength.TryGetValue(model.CmdType, out var packageLength);
            var buffer = new List<byte>() { Consts.StartByte, packageLength };
            buffer.AddRange(model.DeviceId.HexStringToByteArray());
            buffer.Add(((int)model.CmdType).ToByte());

            buffer.Add(model.WineNumber.ToByte());

            var vaildCode = buffer.GetVaildByteCode();
            buffer.Add(vaildCode);
            buffer.Add(Consts.EndByte);

            Console.WriteLine($"App Send Command Req:{Convert.ToHexString(buffer.ToArray())}");
            _customTcpClient.Send(buffer.ToArray());
            return Result.Success;
        }


        [HttpPost]
        public async Task<Result> ModifyId(ModifyIDDown model)
        {
            Consts.CommandPackageLength.TryGetValue(model.CmdType, out var packageLength);
            var buffer = new List<byte>() { Consts.StartByte, packageLength };
            buffer.AddRange(model.DeviceId.HexStringToByteArray());
            buffer.Add(((int)model.CmdType).ToByte());
            var vaildCode = buffer.GetVaildByteCode();
            buffer.Add(vaildCode);
            buffer.Add(Consts.EndByte);

            Console.WriteLine($"App Send Command Req:{Convert.ToHexString(buffer.ToArray())}");
            var result = _customTcpClient.SendThenReceive(buffer.ToArray(), AdapterFilter.WaitAdapter);
            await Console.Out.WriteLineAsync($"App Send Command Res Body:{Convert.ToHexString(((BetweenAndRequestInfo)result.RequestInfo).Body)}");
            return new Result(ResultCode.Success, ((BetweenAndRequestInfo)result.RequestInfo).Data.ToJsonString());
        }
        [HttpPost]
        public Result ChannelCaliOOW(ChannelCalibOOWDown model)
        {
            Consts.CommandPackageLength.TryGetValue(model.CmdType, out var packageLength);
            var buffer = new List<byte>() { Consts.StartByte, packageLength };
            buffer.AddRange(model.DeviceId.HexStringToByteArray());
            buffer.Add(((int)model.CmdType).ToByte());

            buffer.Add(model.ChannelNumber.ToByte());

            var vaildCode = buffer.GetVaildByteCode();
            buffer.Add(vaildCode);
            buffer.Add(Consts.EndByte);

            Console.WriteLine($"App Send Command Req:{Convert.ToHexString(buffer.ToArray())}");
            var result = _customTcpClient.SendThenReceive(buffer.ToArray(), AdapterFilter.WaitAdapter);
            Console.WriteLine($"App Send Command Res Body:{Convert.ToHexString(((BetweenAndRequestInfo)result.RequestInfo).Body)}");
            return new Result(ResultCode.Success, ((BetweenAndRequestInfo)result.RequestInfo).Data.ToJsonString());
        }

        [HttpPost]
        public Result ChannelCaliActOOW(ChannelCalibActOOWDown model)
        {

            if (model.WineNumber > 255)
            {
                return Result.FromError("通道校准实际出酒量必须小于255ml");
            }

            Consts.CommandPackageLength.TryGetValue(model.CmdType, out var packageLength);
            var buffer = new List<byte>() { Consts.StartByte, packageLength };
            buffer.AddRange(model.DeviceId.HexStringToByteArray());
            buffer.Add(((int)model.CmdType).ToByte());

            buffer.Add(model.ChannelNumber.ToByte());
            buffer.Add(model.WineNumber.ToByte());

            var vaildCode = buffer.GetVaildByteCode();
            buffer.Add(vaildCode);
            buffer.Add(Consts.EndByte);

            Console.WriteLine($"App Send Command Req:{Convert.ToHexString(buffer.ToArray())}");
            var result = _customTcpClient.SendThenReceive(buffer.ToArray(), AdapterFilter.WaitAdapter);
            Console.WriteLine($"App Send Command Res Body:{Convert.ToHexString(((BetweenAndRequestInfo)result.RequestInfo).Body)}");
            return new Result(ResultCode.Success, ((BetweenAndRequestInfo)result.RequestInfo).Data.ToJsonString());
        }
        #endregion

        #region 供调用接口

        [HttpPost]
        public async Task<Result> GoOutOfWine(GoOutOfWine cmd)
        {
            return await Mediator.Send(cmd);
        }

        [HttpPost]
        public async Task<Result> GetState(GetStateQuery query)
        {
            return await Mediator.Send(query);
        }

        #endregion
    }
}
